package com.debao.wechat;

import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.debao.common.annotation.Anonymous;
import com.debao.common.constant.Constants;
import com.debao.common.constant.WechatConstants;
import com.debao.common.core.controller.BaseController;
import com.debao.common.core.domain.AjaxResult;
import com.debao.common.enums.OrderTypePrefix;
import com.debao.common.model.TempData;
import com.debao.common.model.WechatTemplateVo;
import com.debao.common.utils.AliyunSmsUtil;
import com.debao.common.utils.SecurityUtils;
import com.debao.common.utils.StringUtils;
import com.debao.common.utils.uuid.IdUtils;
import com.debao.common.utils.wechat.PayUtils;
import com.debao.common.wechat.WechatUtils;
import com.debao.dto.ClassCardPayDto;
import com.debao.dto.GoodsPayDto;
import com.debao.dto.StadiumTablePayDto;
import com.debao.dto.VipCardPayDto;
import com.debao.system.domain.*;
import com.debao.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;

@RestController
@RequestMapping("/api/pay")
@Slf4j
public class ApiPay extends BaseController {

    @Resource
    private IGoodsOrderService goodsOrderService;
    @Resource
    private IJoinOrderService joinOrderService;
    @Resource
    private IConfigService configService;

    @Resource
    private ICourseCardService courseCardService;
    @Resource
    private ICourseCardOrderService cardOrderService;

    @Resource
    private IStadiumTableOrderService stadiumTableOrderService;

    @Resource
    private IStadiumTableService stadiumTableService;

    @Resource
    private IStadiumTableScheduleService stadiumTableScheduleService;

    @Resource
    private IStadiumTableOrderService tableOrderService;

    @Resource
    private IUserCardService userCardService;

    @Autowired
    private IStadiumService stadiumService;

    @Autowired
    private IVipcardOrderService vipcardOrderService;


    // 常量定义
    final int DISCOUNT_DENOMINATOR = 100;


    /**
     * 商品下单订阅通知模板Id
     */
    private static final String templateId = "Q0_qLUgxxRlGpKIqpD9usltLGeTWDCqKmBZvJOAuq_Y";

    /**
     * 场馆预约订单
     */
    @PostMapping("/postStadiumTableOrder")
    public AjaxResult postStadiumTableOrder(@RequestBody @Valid StadiumTablePayDto dto) throws Exception {
        Long userId = SecurityUtils.getUserId();
        String openId = SecurityUtils.getOpenId();
        // 获取桌台
        StadiumTable table = stadiumTableService.selectStadiumTableById(dto.getStadiumTableId());
        if (Objects.isNull(table)) {
            return error("该桌台不存在");
        }
        // 获取需要支付的价格(分)
        Long money = table.getPrice() * dto.getScheduleList().size();
        //判断用户是否是会员,并且会员没有过期
        UserCard userCard = userCardService.selectUserCardByUserId(userId);
        if (!Objects.isNull(userCard) && userCard.getStatus() == Constants.STATUS_1) {
            String discountStr = configService.selectValueByKey(WechatConstants.VIP_TABLE);
            if (StringUtils.isEmpty(discountStr)) {
                throw new NullPointerException("会员折扣为空");
            }
            //计算折扣后的价格
            money = (money * Long.parseLong(discountStr)) / 10;
        }
        // 预约订单号
        String orderNo = OrderTypePrefix.S + "-" + IdUtils.getC(null);
        List<String> timeList = new ArrayList<>();
        dto.getScheduleList().forEach(schedule -> {
            // 判断是否已锁定或者已售出
            boolean isSocked = stadiumTableScheduleService.isSocked(schedule.getId());
            if (isSocked) {
                throw new SecurityException("【" + schedule.getTime() + "】桌台已被锁定或已售出，请重新选择");
            }
            timeList.add(schedule.getTime());
        });
        // 创建订单
        int row = stadiumTableOrderService.insertStadiumTableOrder(new StadiumTableOrder()
                .setStadiumId(dto.getStadiumId())
                .setStadiumTableId(dto.getStadiumTableId())
                .setOrderNo(orderNo)
                .setUserId(userId)
                .setMoney(money)
                .setTime(String.join(",", timeList))
                .setDate(dto.getDate()));
        if (row == 1) {
            // 调用支付
            String xml = PayUtils.paramsFormat("桌台租赁", orderNo, money, openId);
            if (xml.isEmpty()) {
                return AjaxResult.error("支付参数格式化失败");
            }
            // 锁定桌台
            dto.getScheduleList().forEach(schedule -> {
                schedule.setUsable(-1);
                schedule.setAppointUserId(userId);
                schedule.setOrderNo(orderNo);
                stadiumTableScheduleService.updateStadiumTableSchedule(schedule);
            });
            Map<String, String> payParams = PayUtils.miniProgramPayParams(xml);
            payParams.put("orderNo", orderNo);
            Stadium stadium = stadiumService.selectStadiumById(table.getStadiumId());
            return AjaxResult.success(payParams);
        }
        return AjaxResult.error("订单创建失败");
    }

    /**
     * 课程卡订单
     */
    @PostMapping("/postClassOrder")
    public AjaxResult postClassOrder(@RequestBody @Valid ClassCardPayDto dto) throws Exception {
        // 获取课程卡的信息
        CourseCard card = courseCardService.selectCourseCardById(dto.getClassCardId());
        if (Objects.isNull(card)) {
            return AjaxResult.error("课程卡信息不存在");
        }
        if (card.getOnline() == 0) {
            return AjaxResult.error("课程卡已下线");
        }
        if (card.getPrice() == 0) {
            return AjaxResult.error("课程卡金额设置出错");
        }
        Long userId = SecurityUtils.getUserId();
        String openId = SecurityUtils.getOpenId();
        // 获取需要支付的价格(分)
        Long money = card.getPrice();
        //判断用户是否是会员,并且会员没有过期
        UserCard userCard = userCardService.selectUserCardByUserId(userId);
        if (!Objects.isNull(userCard) && userCard.getStatus() == Constants.STATUS_1) {
            String discountStr = configService.selectValueByKey(WechatConstants.VIP_CARD);
            if (StringUtils.isEmpty(discountStr)) {
                throw new NullPointerException("会员折扣为空");
            }
            //计算折扣后的价格
            money = (money * Long.parseLong(discountStr)) / 10;
        }
        // 课程卡订单号
        String orderNo = OrderTypePrefix.K + "-" + IdUtils.getC(null);
        int row = cardOrderService.insertCourseCardOrder(new CourseCardOrder()
                .setOrderNo(orderNo)
                .setUserId(userId)
                .setCourseCardId(card.getId()).setMoney(money));
        if (row == 1) {
            // 调用支付
            String xml = PayUtils.paramsFormat(card.getName(), orderNo, money, openId);
            if (xml.isEmpty()) {
                return AjaxResult.error("支付参数格式化失败");
            }
            Map<String, String> payParams = PayUtils.miniProgramPayParams(xml);
            payParams.put("orderNo", orderNo);
            return AjaxResult.success(payParams);
        }
        return AjaxResult.error("订单创建失败");
    }


    /**
     * 教练入驻订单
     *
     * @return
     */
    @PostMapping("/postJoinOrder")
    public AjaxResult joinOrder() throws Exception {
        Long userId = SecurityUtils.getUserId();
        String openId = SecurityUtils.getOpenId();
        // 入驻订单号
        String orderNo = OrderTypePrefix.C + "-" + IdUtils.getC(null);
        // 费用 （分）
        String price = configService.selectValueByKey(Constants.ENTER_FEE);
        if (price != null && !price.isEmpty()) {
            int row = joinOrderService.insertJoinOrder(new JoinOrder()
                    .setOrderNo(orderNo)
                    .setUserId(userId)
                    .setPayPrice(Long.valueOf(price))
                    .setPrice(Long.valueOf(price)));
            if (row == 1) {
                // 调用支付
                String xml = PayUtils.paramsFormat("教练入驻费用", orderNo, Long.valueOf(price), openId);
                if (xml.isEmpty()) {
                    return AjaxResult.error("支付参数格式化失败");
                }
                Map<String, String> payParams = PayUtils.miniProgramPayParams(xml);
                payParams.put("orderNo", orderNo);
                return AjaxResult.success(payParams);
            }
        }
        return AjaxResult.error("订单创建失败");
    }

    /**
     * 商品购买订单
     *
     * @return
     */
    @PostMapping("/postGoodsOrder")
    public AjaxResult postGoodsOrder(@RequestBody @Valid GoodsPayDto dto) throws Exception {
        Long userId = SecurityUtils.getUserId();
        String openId = SecurityUtils.getOpenId();
        // 商品订单号
        String orderNo = OrderTypePrefix.G + "-" + IdUtils.getC(null);
        // 获取需要支付的价格(分)
        Long money = dto.getPrice();
        //判断用户是否是会员,并且会员没有过期
        UserCard userCard = userCardService.selectUserCardByUserId(userId);
        if (!Objects.isNull(userCard) && userCard.getStatus() == Constants.STATUS_1) {
            String discountStr = configService.selectValueByKey(WechatConstants.VIP_SHOP);
            if (StringUtils.isEmpty(discountStr)) {
                throw new NullPointerException("会员折扣为空");
            }
            //计算折扣后的价格
            money = (money * Long.parseLong(discountStr)) / 10;
        }
        int row = goodsOrderService.insertGoodsOrder(new GoodsOrder()
                .setOrderNo(orderNo)
                .setGoodsId(dto.getGoodsId())
                .setUserId(userId)
                .setAddressId(dto.getAddressId())
                .setQuantity(dto.getQuantity())
                .setMoney(money));
        if (row == 1) {
            // 调用支付
            String xml = PayUtils.paramsFormat(dto.getGoodsName(), orderNo, money, openId);
            if (xml.isEmpty()) {
                return AjaxResult.error("支付参数格式化失败");
            }
            Map<String, String> payParams = PayUtils.miniProgramPayParams(xml);
            payParams.put("orderNo", orderNo);
            return AjaxResult.success("操作成功", payParams);
        }
        return AjaxResult.error("订单创建失败");
    }

    /**
     * 会员卡购买订单
     */
    @PostMapping("/postCardOrder")
    public AjaxResult postCardOrder(@RequestBody @Valid VipCardPayDto dto) throws Exception {
        Long userId = SecurityUtils.getUserId();
        String openId = SecurityUtils.getOpenId();
        // 商品订单号
        String orderNo = OrderTypePrefix.V + "-" + IdUtils.getC(null);
        int row = vipcardOrderService.insertVipcardOrder(new VipcardOrder()
                .setOrderNo(orderNo)
                .setCardId(dto.getCardId())
                .setUserId(userId).setMoney(dto.getPrice()));
        if (row == 1) {
            // 调用支付
            String xml = PayUtils.paramsFormat(dto.getName(), orderNo, dto.getPrice(), openId);
            if (xml.isEmpty()) {
                return AjaxResult.error("支付参数格式化失败");
            }
            Map<String, String> payParams = PayUtils.miniProgramPayParams(xml);
            payParams.put("orderNo", orderNo);
            return AjaxResult.success("操作成功", payParams);
        }
        return AjaxResult.error("订单创建失败");
    }


    /**
     * 微信支付成功回调
     */
    @PostMapping("/callback")
    @Anonymous
    public String callBack(HttpServletRequest request) throws Exception {
        Map<String, String> map = PayUtils.parseXml(request.getInputStream());
        log.info("微信支付成功回调 map = {} ", map);
        String code = map.get("return_code");
        if (code.equals("SUCCESS")) {
            // 获取微信支付订单号
            String transactionId = map.get("transaction_id");
            // 验证签名
            if (PayUtils.checkSign(map)) {
                // 订单状态成功
                String orderNo = map.get("out_trade_no");
                // 判断是什么种类的订单
                handleOrder(orderNo, transactionId);
                return "SUCCESS";
            }
        }
        return "ERROR";
    }

    /**
     * 处理订单
     *
     * @param orderNo
     * @param transactionId
     * @throws Exception
     */
    private void handleOrder(String orderNo, String transactionId) throws Exception {
        // 商品订单
        if (orderNo.contains(OrderTypePrefix.G.name())) {
            goodsOrderService.paySucHandleOrder(orderNo, transactionId);
            return;
        }
        // 入驻订单
        if (orderNo.contains(OrderTypePrefix.C.name())) {
            joinOrderService.paySucHandleOrder(orderNo, transactionId);
            return;
        }
        // 课程卡订单
        if (orderNo.contains(OrderTypePrefix.K.name())) {
            cardOrderService.paySucHandleOrder(orderNo, transactionId);
            return;
        }
        // 场馆预约订单
        if (orderNo.contains(OrderTypePrefix.S.name())) {
            tableOrderService.paySucHandleOrder(orderNo, transactionId);
        }
        // 会员卡订单
        if (orderNo.contains(OrderTypePrefix.V.name())) {
            vipcardOrderService.paySucHandleOrder(orderNo, transactionId);
        }

    }

    /**
     * 获取订单状态
     */
    @PostMapping("/getOrderStatus")
    public AjaxResult getOrderStatus(String orderNo) {
        boolean paySuccess = false;
        // 商品订单
        if (orderNo.contains(OrderTypePrefix.G.name())) {
            GoodsOrder goodsOrder = goodsOrderService.selectGoodsOrderByOrderNo(orderNo);
            if (Objects.nonNull(goodsOrder) && goodsOrder.getStatus().equals("Success")) {
                paySuccess = true;
            }
            return AjaxResult.success(paySuccess);
        }
        // 入驻订单
        if (orderNo.contains(OrderTypePrefix.C.name())) {
            JoinOrder joinOrder = joinOrderService.selectJoinOrderByOrderNo(orderNo);
            if (Objects.nonNull(joinOrder) && joinOrder.getStatus().equals("Success")) {
                paySuccess = true;
            }
            return AjaxResult.success(paySuccess);
        }
        return AjaxResult.success("订单不存在");
    }


    @GetMapping("/sendSms")
    @Anonymous
    public AjaxResult sendSms(String phone, String content) {
        //异步方式实现短信推送 通知给用户
        Thread threadMsg = new Thread(() -> {
            synchronized (this) {
                HashMap<String, String> coachMap = new HashMap<>();
                coachMap.put("course", "一对一私教课");
                coachMap.put("name", "陈需");
                try {
                    AliyunSmsUtil.sendSms("15890715316", "SMS_474635107", JSONObject.toJSONString(coachMap));
                } catch (ClientException e) {
                    throw new RuntimeException(e);
                }
//                //订阅消息通知 通知给下单的用户
//                String token = configService.selectValueByKey(WechatConstants.APP_TOKEN);
//                String orderNo = "S-202410111923332551602671";
//                Map<String, TempData> data = new HashMap<>();
//                data.put("thing2", new TempData("一对一私教课"));
//                data.put("thing1", new TempData("陈需"));
//                WechatUtils.postTemplateData(new WechatTemplateVo().setTemplateId("D2NFSL7xz_mvMh9lfcJKNSCDvnh8Z0I0LVul5HlAXuw").setToken(token).setOpenid("o8s3J4sbNJnUhO63s9R-sw4mjAJ0").setData(data).setPage("/subPackages/order/details/stadum_detail?orderNo=" + orderNo));
            }
        });
        threadMsg.start();
        return AjaxResult.success();
    }
}

